﻿using DropBoxClient.Entities;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.Serialization.Json;
using System.Text;

namespace DropBoxClient.Framework
{
    class WebOperation<TResponse>
    {
        private string _url;
        private string _accessToken;
        private string _methodType;
        private NameValueCollection _parameters;
        private Stream _stream;

        internal WebOperation(string url, string accessToken, string methodType, NameValueCollection parameters = null, Stream stream = null)
        {
            _url = url;
            _accessToken = accessToken;
            _methodType = methodType;
            _parameters = parameters;
            _stream = stream;
        }

        internal TResponse Execute()
        {
            TResponse responseObject = default(TResponse);
            var request = WebRequest.Create(_url);
            request.Headers.Add(HttpRequestHeader.Authorization, "Bearer " + _accessToken);
            request.Method = _methodType;
            if (request.Method == StringConstants.PostMethodType && _parameters != null && _parameters.Count > 0)
            {
                var parameterString = GetParametersAsString();
                byte[] buffer = Encoding.UTF8.GetBytes(parameterString);
                request.ContentLength = buffer.Length;
                request.ContentType = "application/x-www-form-urlencoded";
                using (var writer = new BinaryWriter(request.GetRequestStream()))
                {
                    writer.Write(buffer);
                }
            }
            else if (_stream != null)
            {
                request.ContentType = "application/octet-stream";
                _stream.Position = 0;
                long bufferSize = request.ContentLength = _stream.Length;
                byte[] buffer = new byte[bufferSize];
                _stream.Read(buffer, 0, (int)bufferSize);
                _stream.Close();
                
                using (var writer = new BinaryWriter(request.GetRequestStream()))
                {
                    writer.Write(buffer);
                }
            }
            using (var response = request.GetResponse())
            {
                var serializer = new DataContractJsonSerializer(typeof(TResponse));
                responseObject = (TResponse)serializer.ReadObject(response.GetResponseStream());
            }
            return responseObject;
        }

        private string GetParametersAsString()
        {
            string parameterString = string.Empty;
            foreach (string key in _parameters.AllKeys)
                parameterString += string.Format("{0}={1}&", key, _parameters[key]);
            return parameterString.Substring(0, parameterString.Length - 1);
        }
    }
}
